package edu.dhbw.proandroidar4ardemo;

import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.hardware.Camera;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;


import edu.dhbw.andar.view.HorizonView;


public class MainActivity extends Activity {

    LocationManager locationManager;

    Button updateAltitudeButton;
    TextView altitudeValue;

    double currentAltitude;
    double pitch;
    double newAltitude;
    double changeInAltitude;
    double thetaSin; // 存储俯仰角的正弦值。

    boolean inPreview;

    Camera camera;
    SurfaceView cameraPreView;
    SurfaceHolder previewHolder;

    HorizonView horizonView;
    SensorManager sensorManager;

    private static final String TAG = "MainActivity";

    // 方向传感器
    int orientationSensor;
    // 存储设备的航向、俯仰和横摇。
    float headingAngle; // 屏幕的方向的角度，即旋转屏幕方向会改变此值
    float pitchAngle;  // 手机的竖直倾斜角度
    float rollAngle;  //  手机横向倾斜的角度

    // 加速度传感器
    int accelerometerSensor;
    // x,y,z轴的加速度
    float xAxis;
    float yAxis;
    float zAxis;

    // 我们只需要从Location对象获取纬度、经度和高度，但如果需要，还可以获取方位、时间等等
    double latitude; // 纬度
    double longitude; // 经度
    double altitude; // 高度

    float[] aValues = new float[3];
    float[] mValues = new float[3];

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);

        if (ContextCompat.checkSelfPermission(this,
                Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.CAMERA}, 1);
        }

        locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 2000,
                1, locationListener);

        inPreview = false;

        cameraPreView = (SurfaceView) findViewById(R.id.cameraPreview);
        previewHolder = cameraPreView.getHolder();
        previewHolder.addCallback(surfaceCallback);
        previewHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

        altitudeValue = (TextView) findViewById(R.id.altitudeValue);
        updateAltitudeButton = (Button) findViewById(R.id.altitudeUpdateButton);
        updateAltitudeButton.setOnClickListener(new View.OnClickListener() {
            public void onClick(View arg0) {
                updateAltitude();
            }
        });



        horizonView = (HorizonView)this.findViewById(R.id.horizonView);
        sensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE);
        updateOrientation(new float[] {0, 0, 0});
    }

    private void updateOrientation(float[] values) {

        if (horizonView != null) {
            horizonView.setBearing(values[0]);
            horizonView.setPitch(values[1]);
            horizonView.setRoll(-values[2]);
            horizonView.invalidate(); // 重绘
        }
    }

    @Override
    public void onResume() {
        super.onResume();
        if (ContextCompat.checkSelfPermission(this,
                Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.CAMERA}, 1);
        }
        locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
                2000, 1, locationListener);

        Sensor accelerometer =
                sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        Sensor magField =
                sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
        sensorManager.registerListener(sensorEventListener, accelerometer,
                SensorManager.SENSOR_DELAY_FASTEST);
        sensorManager.registerListener(sensorEventListener, magField,
                SensorManager.SENSOR_DELAY_FASTEST);

        camera = Camera.open();

    }

    @Override
    protected void onPause() {
        if (inPreview){
            camera.stopPreview();
        }
        locationManager.removeUpdates(locationListener);
        // 取消注册传感器
        sensorManager.unregisterListener(sensorEventListener);
        camera.release();
        camera = null;
        inPreview = false;
        super.onPause();
    }

    @Override protected void onStop() {
        sensorManager.unregisterListener(sensorEventListener);
        super.onStop();
    }

    final SensorEventListener sensorEventListener = new SensorEventListener() {
        /**
         * 当传感器的值发生变化时，我们使用onSensorChanged()方法接收更新
         * @param event SensorEvent事件
         */
        @Override
        public void onSensorChanged(SensorEvent event) {
            // 过滤除方向传感器外的内容
            if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) aValues = event.values;
            if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) mValues = event.values;
            updateOrientation(calculateOrientation());
        }

        @Override
        public void onAccuracyChanged(Sensor sensor, int accuracy) {

        }
    };

    /**
     * 计算水平数据
     * @return
     */
    private float[] calculateOrientation() {
        float[] values = new float[3];
        float[] R = new float[9];
        float[] outR = new float[9];
        SensorManager.getRotationMatrix(R, null, aValues, mValues);
        SensorManager.remapCoordinateSystem(R,
                SensorManager.AXIS_X, SensorManager.AXIS_Z, outR);
        SensorManager.getOrientation(outR, values);
        values[0] = (float) Math.toDegrees(values[0]);
        values[1] = (float) Math.toDegrees(values[1]);
        values[2] = (float) Math.toDegrees(values[2]);
        pitch = values[1];
        return values;
    }

    LocationListener locationListener = new LocationListener() {
        @Override
        public void onLocationChanged(Location location) {
            currentAltitude = location.getAltitude();
            Log.e(TAG, "currentAltitude: " + currentAltitude);
            altitudeValue.setText(String.valueOf(currentAltitude));
        }
        @Override
        public void onProviderDisabled(String arg0) { //Not Used
        }
        @Override
        public void onProviderEnabled(String arg0) { //Not Used
        }
        @Override
        public void onStatusChanged(String arg0, int arg1, Bundle arg2) { //Not Used
        }
    };

    public void updateAltitude() {
        int time = 300;
        float speed = 4.5f;
        double distanceMoved = (speed * time) * 0.3048;
        Log.e(TAG, "pitch: " + pitch + " currentAltitude: " + currentAltitude);
        if (pitch != 0 && currentAltitude != 0) {

            thetaSin = Math.sin(pitch);
            changeInAltitude = thetaSin * distanceMoved;
            newAltitude = currentAltitude + changeInAltitude;
            altitudeValue.setText(String.valueOf(newAltitude));
        } else {
            altitudeValue.setText("Try Again");
        }
    }


    /**
     * 获得最好的窗口大小
     * @param width 宽度
     * @param height 高度
     * @param parameters 参数数组
     * @return
     */
    private Camera.Size getBestPreviewSize(int width, int height, Camera.Parameters parameters) {
        Camera.Size result = null;

        for (Camera.Size size : parameters.getSupportedPreviewSizes()){
            if (size.width <= width && size.height <= height){
                if (result == null){
                    result = size;
                } else{
                    int resultArea = result.width * result.height;
                    int newArea = size.width * size.height;

                    if (newArea > resultArea){
                        result = size;
                    }
                }

            }
        }
        return result;
    }

    /**
     * 回调
     */
    SurfaceHolder.Callback surfaceCallback = new SurfaceHolder.Callback() {
        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            try {
                camera.setPreviewDisplay(previewHolder);
            } catch (Throwable e) {
                Log.e(TAG, "surfaceCreated Failed", e);
            }
        }

        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
            Camera.Parameters parameters = camera.getParameters();
            Camera.Size size = getBestPreviewSize(width, height, parameters);

            if (size != null){
                parameters.setPreviewSize(size.width, size.height);
                camera.setParameters(parameters);
                camera.startPreview();
                inPreview = true;
            }
        }

        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {
            camera.stopPreview();
            camera.release();
            camera = null;
        }
    };


}
